using UnityEngine;
using System.Collections;

public class ValueEvent{
	public static string[] EaseTypeStr = {
		"easeInQuad",
		"easeOutQuad",
		"easeInOutQuad",
		"easeInCubic",
		"easeOutCubic",
		"easeInOutCubic",
		"easeInQuart",
		"easeOutQuart",
		"easeInOutQuart",
		"easeInQuint",
		"easeOutQuint",
		"easeInOutQuint",
		"easeInSine",
		"easeOutSine",
		"easeInOutSine",
		"easeInExpo",
		"easeOutExpo",
		"easeInOutExpo",
		"easeInCirc",
		"easeOutCirc",
		"easeInOutCirc",
		"linear",
		"spring",
		"easeInBounce",
		"easeOutBounce",
		"easeInOutBounce",
		"easeInBack",
		"easeOutBack",
		"easeInOutBack",
		"easeInElastic",
		"easeOutElastic",
		"easeInOutElastic",
	};
	public enum EaseType{
		easeInQuad,
		easeOutQuad,
		easeInOutQuad,
		easeInCubic,
		easeOutCubic,
		easeInOutCubic,
		easeInQuart,
		easeOutQuart,
		easeInOutQuart,
		easeInQuint,
		easeOutQuint,
		easeInOutQuint,
		easeInSine,
		easeOutSine,
		easeInOutSine,
		easeInExpo,
		easeOutExpo,
		easeInOutExpo,
		easeInCirc,
		easeOutCirc,
		easeInOutCirc,
		linear,
		spring,
		/* GFX47 MOD START */
		//bounce,
		easeInBounce,
		easeOutBounce,
		easeInOutBounce,
		/* GFX47 MOD END */
		easeInBack,
		easeOutBack,
		easeInOutBack,
		/* GFX47 MOD START */
		//elastic,
		easeInElastic,
		easeOutElastic,
		easeInOutElastic,
		//		/* GFX47 MOD END */
		//		punch
	}
	/// <summary>
	/// The type of easing to use based on Robert Penner's open source easing equations (http://www.robertpenner.com/easing_terms_of_use.html).
	/// </summary>
	public float Middle =1;
	public static float WrapValue( float v, float start, float end, WrapMode wMode )
	{
		switch( wMode )
		{
		case WrapMode.Clamp:
		case WrapMode.ClampForever:
			return Mathf.Clamp( v, start, end );
		case WrapMode.Default:
		case WrapMode.Loop:
			return Mathf.Repeat( v, end - start ) + start;
		case WrapMode.PingPong:
			return Mathf.PingPong( v, end - start ) + start;
		default:
			return v;
		}
	}
	public float GetValue( EaseType easeType,float start,float end,float time,WrapMode wMode = WrapMode.Default){
		if(wMode == WrapMode.Default){
			//照顾旧的
			if (Middle != 1) {
				if(time > Middle){
					time = (time - Middle)/(1 - Middle);
					float save = end;
					end = start;
					start = save;
				}
				else{
					time = time/Middle;
				}
			}
		}
		else{
			time = WrapValue(time,start,end,wMode);
		}
		switch (easeType){
		case EaseType.easeInQuad:
			return easeInQuad(start,end,time);
		case EaseType.easeOutQuad:
			return easeOutQuad(start,end,time);
		case EaseType.easeInOutQuad:
			return easeInOutQuad(start,end,time);
		case EaseType.easeInCubic:
			return easeInCubic(start,end,time);
		case EaseType.easeOutCubic:
			return easeOutCubic(start,end,time);
		case EaseType.easeInOutCubic:
			return easeInOutCubic(start,end,time);
		case EaseType.easeInQuart:
			return easeInQuart(start,end,time);
		case EaseType.easeOutQuart:
			return easeOutQuart(start,end,time);
		case EaseType.easeInOutQuart:
			return easeInOutQuart(start,end,time);
		case EaseType.easeInQuint:
			return easeInQuint(start,end,time);
		case EaseType.easeOutQuint:
			return easeOutQuint(start,end,time);
		case EaseType.easeInOutQuint:
			return easeInOutQuint(start,end,time);
		case EaseType.easeInSine:
			return easeInSine(start,end,time);
		case EaseType.easeOutSine:
			return easeOutSine(start,end,time);
		case EaseType.easeInOutSine:
			return easeInOutSine(start,end,time);
		case EaseType.easeInExpo:
			return easeInExpo(start,end,time);
		case EaseType.easeOutExpo:
			return easeOutExpo(start,end,time);
		case EaseType.easeInOutExpo:
			return easeInOutExpo(start,end,time);
		case EaseType.easeInCirc:
			return easeInCirc(start,end,time);
		case EaseType.easeOutCirc:
			return easeOutCirc(start,end,time);
		case EaseType.easeInOutCirc:
			return easeInOutCirc(start,end,time);
		case EaseType.linear:
			return linear(start,end,time);
		case EaseType.spring:
			return spring(start,end,time);
			/* GFX47 MOD START */
			/*case EaseType.bounce:
			ease = new EasingFunction(bounce);
			break;*/
		case EaseType.easeInBounce:
			return easeInBounce(start,end,time);
		case EaseType.easeOutBounce:
			return easeOutBounce(start,end,time);
		case EaseType.easeInOutBounce:
			return easeInOutBounce(start,end,time);
			/* GFX47 MOD END */
		case EaseType.easeInBack:
			return easeInBack(start,end,time);
		case EaseType.easeOutBack:
			return easeOutBack(start,end,time);
		case EaseType.easeInOutBack:
			return easeInOutBack(start,end,time);
			/* GFX47 MOD START */
			/*case EaseType.elastic:
			ease = new EasingFunction(elastic);
			break;*/
		case EaseType.easeInElastic:
			return easeInElastic(start,end,time);
		case EaseType.easeOutElastic:
			return easeOutElastic(start,end,time);
		case EaseType.easeInOutElastic:
			return easeInOutElastic(start,end,time);
			/* GFX47 MOD END */
		}
		return 0;
	}
	#region EaseTypeFun
	private float linear(float start, float end, float value){
		return Mathf.Lerp(start, end, value);
	}
	
	private float clerp(float start, float end, float value){
		float min = 0.0f;
		float max = 360.0f;
		float half = Mathf.Abs((max - min) / 2.0f);
		float retval = 0.0f;
		float diff = 0.0f;
		if ((end - start) < -half){
			diff = ((max - start) + end) * value;
			retval = start + diff;
		}else if ((end - start) > half){
			diff = -((max - end) + start) * value;
			retval = start + diff;
		}else retval = start + (end - start) * value;
		return retval;
	}
	
	private float spring(float start, float end, float value){
		value = Mathf.Clamp01(value);
		value = (Mathf.Sin(value * Mathf.PI * (0.2f + 2.5f * value * value * value)) * Mathf.Pow(1f - value, 2.2f) + value) * (1f + (1.2f * (1f - value)));
		return start + (end - start) * value;
	}
	
	private float easeInQuad(float start, float end, float value){
		end -= start;
		return end * value * value + start;
	}
	
	private float easeOutQuad(float start, float end, float value){
		end -= start;
		return -end * value * (value - 2) + start;
	}
	
	private float easeInOutQuad(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value + start;
		value--;
		return -end / 2 * (value * (value - 2) - 1) + start;
	}
	
	private float easeInCubic(float start, float end, float value){
		end -= start;
		return end * value * value * value + start;
	}
	
	private float easeOutCubic(float start, float end, float value){
		value--;
		end -= start;
		return end * (value * value * value + 1) + start;
	}
	
	private float easeInOutCubic(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value + start;
		value -= 2;
		return end / 2 * (value * value * value + 2) + start;
	}
	
	private float easeInQuart(float start, float end, float value){
		end -= start;
		return end * value * value * value * value + start;
	}
	
	private float easeOutQuart(float start, float end, float value){
		value--;
		end -= start;
		return -end * (value * value * value * value - 1) + start;
	}
	
	private float easeInOutQuart(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value * value + start;
		value -= 2;
		return -end / 2 * (value * value * value * value - 2) + start;
	}
	
	private float easeInQuint(float start, float end, float value){
		end -= start;
		return end * value * value * value * value * value + start;
	}
	
	private float easeOutQuint(float start, float end, float value){
		value--;
		end -= start;
		return end * (value * value * value * value * value + 1) + start;
	}
	
	private float easeInOutQuint(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value * value * value + start;
		value -= 2;
		return end / 2 * (value * value * value * value * value + 2) + start;
	}
	
	private float easeInSine(float start, float end, float value){
		end -= start;
		return -end * Mathf.Cos(value / 1 * (Mathf.PI / 2)) + end + start;
	}
	
	private float easeOutSine(float start, float end, float value){
		end -= start;
		return end * Mathf.Sin(value / 1 * (Mathf.PI / 2)) + start;
	}
	
	private float easeInOutSine(float start, float end, float value){
		end -= start;
		return -end / 2 * (Mathf.Cos(Mathf.PI * value / 1) - 1) + start;
	}
	
	private float easeInExpo(float start, float end, float value){
		end -= start;
		return end * Mathf.Pow(2, 10 * (value / 1 - 1)) + start;
	}
	
	private float easeOutExpo(float start, float end, float value){
		end -= start;
		return end * (-Mathf.Pow(2, -10 * value / 1) + 1) + start;
	}
	
	private float easeInOutExpo(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * Mathf.Pow(2, 10 * (value - 1)) + start;
		value--;
		return end / 2 * (-Mathf.Pow(2, -10 * value) + 2) + start;
	}
	
	private float easeInCirc(float start, float end, float value){
		end -= start;
		return -end * (Mathf.Sqrt(1 - value * value) - 1) + start;
	}
	
	private float easeOutCirc(float start, float end, float value){
		value--;
		end -= start;
		return end * Mathf.Sqrt(1 - value * value) + start;
	}
	
	private float easeInOutCirc(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return -end / 2 * (Mathf.Sqrt(1 - value * value) - 1) + start;
		value -= 2;
		return end / 2 * (Mathf.Sqrt(1 - value * value) + 1) + start;
	}
	
	/* GFX47 MOD START */
	private float easeInBounce(float start, float end, float value){
		end -= start;
		float d = 1f;
		return end - easeOutBounce(0, end, d-value) + start;
	}
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	//private float bounce(float start, float end, float value){
	private float easeOutBounce(float start, float end, float value){
		value /= 1f;
		end -= start;
		if (value < (1 / 2.75f)){
			return end * (7.5625f * value * value) + start;
		}else if (value < (2 / 2.75f)){
			value -= (1.5f / 2.75f);
			return end * (7.5625f * (value) * value + .75f) + start;
		}else if (value < (2.5 / 2.75)){
			value -= (2.25f / 2.75f);
			return end * (7.5625f * (value) * value + .9375f) + start;
		}else{
			value -= (2.625f / 2.75f);
			return end * (7.5625f * (value) * value + .984375f) + start;
		}
	}
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	private float easeInOutBounce(float start, float end, float value){
		end -= start;
		float d = 1f;
		if (value < d/2) return easeInBounce(0, end, value*2) * 0.5f + start;
		else return easeOutBounce(0, end, value*2-d) * 0.5f + end*0.5f + start;
	}
	/* GFX47 MOD END */
	
	private float easeInBack(float start, float end, float value){
		end -= start;
		value /= 1;
		float s = 1.70158f;
		return end * (value) * value * ((s + 1) * value - s) + start;
	}
	
	private float easeOutBack(float start, float end, float value){
		float s = 1.70158f;
		end -= start;
		value = (value / 1) - 1;
		return end * ((value) * value * ((s + 1) * value + s) + 1) + start;
	}
	
	private float easeInOutBack(float start, float end, float value){
		float s = 1.70158f;
		end -= start;
		value /= .5f;
		if ((value) < 1){
			s *= (1.525f);
			return end / 2 * (value * value * (((s) + 1) * value - s)) + start;
		}
		value -= 2;
		s *= (1.525f);
		return end / 2 * ((value) * value * (((s) + 1) * value + s) + 2) + start;
	}
	
	private float punch(float amplitude, float value){
		float s = 9;
		if (value == 0){
			return 0;
		}
		if (value == 1){
			return 0;
		}
		float period = 1 * 0.3f;
		s = period / (2 * Mathf.PI) * Mathf.Asin(0);
		return (amplitude * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * 1 - s) * (2 * Mathf.PI) / period));
	}
	
	/* GFX47 MOD START */
	private float easeInElastic(float start, float end, float value){
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d) == 1) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		return -(a * Mathf.Pow(2, 10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start;
	}		
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	//private float elastic(float start, float end, float value){
	private float easeOutElastic(float start, float end, float value){
		/* GFX47 MOD END */
		//Thank you to rafael.marteleto for fixing this as a port over from Pedro's UnityTween
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d) == 1) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		return (a * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) + end + start);
	}		
	
	/* GFX47 MOD START */
	private float easeInOutElastic(float start, float end, float value){
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d/2) == 2) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		if (value < 1) return -0.5f * (a * Mathf.Pow(2, 10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start;
		return a * Mathf.Pow(2, -10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) * 0.5f + end + start;
	}		
	#endregion
}

public class EasyValueLerp{
	public static Vector3  LerpValue3(Vector3 start,Vector3 end,float time,ValueEvent.EaseType easytype  = ValueEvent.EaseType.linear,WrapMode wMode = WrapMode.Clamp){
		return new Vector3 (LerpValue (start.x, end.x,time, easytype, wMode), LerpValue (start.y, end.y,time, easytype, wMode), LerpValue (start.z, end.z,time, easytype, wMode));
	}
	public static Vector2  LerpValue2(Vector3 start,Vector3 end,float time,ValueEvent.EaseType easytype  = ValueEvent.EaseType.linear,WrapMode wMode = WrapMode.Clamp){
		return new Vector2 (LerpValue (start.x, end.x,time, easytype, wMode), LerpValue (start.y, end.y,time, easytype, wMode));
	}
	public static Color  LerpColor(Color start,Color end,float time,ValueEvent.EaseType easytype  = ValueEvent.EaseType.linear,WrapMode wMode = WrapMode.Clamp){
		return new Color (LerpValue (start.r, end.r,time, easytype, wMode), LerpValue (start.g, end.g,time, easytype, wMode),LerpValue (start.b, end.b,time, easytype, wMode),LerpValue (start.a, end.a,time, easytype, wMode));
	}
	public static float LerpValue(float start,float end,float time,ValueEvent.EaseType easeType = ValueEvent.EaseType.linear,WrapMode wMode = WrapMode.Clamp){
		return 	GetValue (easeType, start, end, time, wMode);
	} 

	public static float WrapValue( float v, float start, float end, WrapMode wMode )
	{
		switch( wMode )
		{
		case WrapMode.Clamp:
		case WrapMode.ClampForever:
			return Mathf.Clamp( v, start, end );
		case WrapMode.Default:
		case WrapMode.Loop:
			return Mathf.Repeat( v, end - start ) + start;
		case WrapMode.PingPong:
			return Mathf.PingPong( v, end - start ) + start;
		default:
			return v;
		}
	}
	public static float GetValue( ValueEvent.EaseType easeType,float start,float end,float time,WrapMode wMode = WrapMode.Clamp){
		time = WrapValue(time,0,1,wMode);
		switch (easeType){
		case ValueEvent.EaseType.easeInQuad:
			return easeInQuad(start,end,time);
		case ValueEvent.EaseType.easeOutQuad:
			return easeOutQuad(start,end,time);
		case ValueEvent.EaseType.easeInOutQuad:
			return easeInOutQuad(start,end,time);
		case ValueEvent.EaseType.easeInCubic:
			return easeInCubic(start,end,time);
		case ValueEvent.EaseType.easeOutCubic:
			return easeOutCubic(start,end,time);
		case ValueEvent.EaseType.easeInOutCubic:
			return easeInOutCubic(start,end,time);
		case ValueEvent.EaseType.easeInQuart:
			return easeInQuart(start,end,time);
		case ValueEvent.EaseType.easeOutQuart:
			return easeOutQuart(start,end,time);
		case ValueEvent.EaseType.easeInOutQuart:
			return easeInOutQuart(start,end,time);
		case ValueEvent.EaseType.easeInQuint:
			return easeInQuint(start,end,time);
		case ValueEvent.EaseType.easeOutQuint:
			return easeOutQuint(start,end,time);
		case ValueEvent.EaseType.easeInOutQuint:
			return easeInOutQuint(start,end,time);
		case ValueEvent.EaseType.easeInSine:
			return easeInSine(start,end,time);
		case ValueEvent.EaseType.easeOutSine:
			return easeOutSine(start,end,time);
		case ValueEvent.EaseType.easeInOutSine:
			return easeInOutSine(start,end,time);
		case ValueEvent.EaseType.easeInExpo:
			return easeInExpo(start,end,time);
		case ValueEvent.EaseType.easeOutExpo:
			return easeOutExpo(start,end,time);
		case ValueEvent.EaseType.easeInOutExpo:
			return easeInOutExpo(start,end,time);
		case ValueEvent.EaseType.easeInCirc:
			return easeInCirc(start,end,time);
		case ValueEvent.EaseType.easeOutCirc:
			return easeOutCirc(start,end,time);
		case ValueEvent.EaseType.easeInOutCirc:
			return easeInOutCirc(start,end,time);
		case ValueEvent.EaseType.linear:
			return linear(start,end,time);
		case ValueEvent.EaseType.spring:
			return spring(start,end,time);
			/* GFX47 MOD START */
			/*case EaseType.bounce:
			ease = new EasingFunction(bounce);
			break;*/
		case ValueEvent.EaseType.easeInBounce:
			return easeInBounce(start,end,time);
		case ValueEvent.EaseType.easeOutBounce:
			return easeOutBounce(start,end,time);
		case ValueEvent.EaseType.easeInOutBounce:
			return easeInOutBounce(start,end,time);
			/* GFX47 MOD END */
		case ValueEvent.EaseType.easeInBack:
			return easeInBack(start,end,time);
		case ValueEvent.EaseType.easeOutBack:
			return easeOutBack(start,end,time);
		case ValueEvent.EaseType.easeInOutBack:
			return easeInOutBack(start,end,time);
			/* GFX47 MOD START */
			/*case EaseType.elastic:
			ease = new EasingFunction(elastic);
			break;*/
		case ValueEvent.EaseType.easeInElastic:
			return easeInElastic(start,end,time);
		case ValueEvent.EaseType.easeOutElastic:
			return easeOutElastic(start,end,time);
		case ValueEvent.EaseType.easeInOutElastic:
			return easeInOutElastic(start,end,time);
			/* GFX47 MOD END */
		}
		return 0;
	}
	#region EaseTypeFun
	private static float linear(float start, float end, float value){
		float v = Mathf.Lerp(start, end, value);
		return v;
	}
	
	private float clerp(float start, float end, float value){
		float min = 0.0f;
		float max = 360.0f;
		float half = Mathf.Abs((max - min) / 2.0f);
		float retval = 0.0f;
		float diff = 0.0f;
		if ((end - start) < -half){
			diff = ((max - start) + end) * value;
			retval = start + diff;
		}else if ((end - start) > half){
			diff = -((max - end) + start) * value;
			retval = start + diff;
		}else retval = start + (end - start) * value;
		return retval;
	}
	
	private static float spring(float start, float end, float value){
		value = Mathf.Clamp01(value);
		value = (Mathf.Sin(value * Mathf.PI * (0.2f + 2.5f * value * value * value)) * Mathf.Pow(1f - value, 2.2f) + value) * (1f + (1.2f * (1f - value)));
		return start + (end - start) * value;
	}
	
	private static float easeInQuad(float start, float end, float value){
		end -= start;
		return end * value * value + start;
	}
	
	private static float easeOutQuad(float start, float end, float value){
		end -= start;
		return -end * value * (value - 2) + start;
	}
	
	private static float easeInOutQuad(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value + start;
		value--;
		return -end / 2 * (value * (value - 2) - 1) + start;
	}
	
	private static float easeInCubic(float start, float end, float value){
		end -= start;
		return end * value * value * value + start;
	}
	
	private static float easeOutCubic(float start, float end, float value){
		value--;
		end -= start;
		return end * (value * value * value + 1) + start;
	}
	
	private static float easeInOutCubic(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value + start;
		value -= 2;
		return end / 2 * (value * value * value + 2) + start;
	}
	
	private static float easeInQuart(float start, float end, float value){
		end -= start;
		return end * value * value * value * value + start;
	}
	
	private static float easeOutQuart(float start, float end, float value){
		value--;
		end -= start;
		return -end * (value * value * value * value - 1) + start;
	}
	
	private static float easeInOutQuart(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value * value + start;
		value -= 2;
		return -end / 2 * (value * value * value * value - 2) + start;
	}
	
	private static float easeInQuint(float start, float end, float value){
		end -= start;
		return end * value * value * value * value * value + start;
	}
	
	private static float easeOutQuint(float start, float end, float value){
		value--;
		end -= start;
		return end * (value * value * value * value * value + 1) + start;
	}
	
	private static float easeInOutQuint(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * value * value * value * value * value + start;
		value -= 2;
		return end / 2 * (value * value * value * value * value + 2) + start;
	}
	
	private static float easeInSine(float start, float end, float value){
		end -= start;
		return -end * Mathf.Cos(value / 1 * (Mathf.PI / 2)) + end + start;
	}
	
	private static float easeOutSine(float start, float end, float value){
		end -= start;
		return end * Mathf.Sin(value / 1 * (Mathf.PI / 2)) + start;
	}
	
	private static float easeInOutSine(float start, float end, float value){
		end -= start;
		return -end / 2 * (Mathf.Cos(Mathf.PI * value / 1) - 1) + start;
	}
	
	private static float easeInExpo(float start, float end, float value){
		end -= start;
		return end * Mathf.Pow(2, 10 * (value / 1 - 1)) + start;
	}
	
	private static float easeOutExpo(float start, float end, float value){
		end -= start;
		return end * (-Mathf.Pow(2, -10 * value / 1) + 1) + start;
	}
	
	private static float easeInOutExpo(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return end / 2 * Mathf.Pow(2, 10 * (value - 1)) + start;
		value--;
		return end / 2 * (-Mathf.Pow(2, -10 * value) + 2) + start;
	}
	
	private static float easeInCirc(float start, float end, float value){
		end -= start;
		return -end * (Mathf.Sqrt(1 - value * value) - 1) + start;
	}
	
	private static float easeOutCirc(float start, float end, float value){
		value--;
		end -= start;
		return end * Mathf.Sqrt(1 - value * value) + start;
	}
	
	private static float easeInOutCirc(float start, float end, float value){
		value /= .5f;
		end -= start;
		if (value < 1) return -end / 2 * (Mathf.Sqrt(1 - value * value) - 1) + start;
		value -= 2;
		return end / 2 * (Mathf.Sqrt(1 - value * value) + 1) + start;
	}
	
	/* GFX47 MOD START */
	private static float easeInBounce(float start, float end, float value){
		end -= start;
		float d = 1f;
		return end - easeOutBounce(0, end, d-value) + start;
	}
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	//private float bounce(float start, float end, float value){
	private static float easeOutBounce(float start, float end, float value){
		value /= 1f;
		end -= start;
		if (value < (1 / 2.75f)){
			return end * (7.5625f * value * value) + start;
		}else if (value < (2 / 2.75f)){
			value -= (1.5f / 2.75f);
			return end * (7.5625f * (value) * value + .75f) + start;
		}else if (value < (2.5 / 2.75)){
			value -= (2.25f / 2.75f);
			return end * (7.5625f * (value) * value + .9375f) + start;
		}else{
			value -= (2.625f / 2.75f);
			return end * (7.5625f * (value) * value + .984375f) + start;
		}
	}
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	private static float easeInOutBounce(float start, float end, float value){
		end -= start;
		float d = 1f;
		if (value < d/2) return easeInBounce(0, end, value*2) * 0.5f + start;
		else return easeOutBounce(0, end, value*2-d) * 0.5f + end*0.5f + start;
	}
	/* GFX47 MOD END */
	
	private static float easeInBack(float start, float end, float value){
		end -= start;
		value /= 1;
		float s = 1.70158f;
		return end * (value) * value * ((s + 1) * value - s) + start;
	}
	
	private static float easeOutBack(float start, float end, float value){
		float s = 1.70158f;
		end -= start;
		value = (value / 1) - 1;
		return end * ((value) * value * ((s + 1) * value + s) + 1) + start;
	}
	
	private static float easeInOutBack(float start, float end, float value){
		float s = 1.70158f;
		end -= start;
		value /= .5f;
		if ((value) < 1){
			s *= (1.525f);
			return end / 2 * (value * value * (((s) + 1) * value - s)) + start;
		}
		value -= 2;
		s *= (1.525f);
		return end / 2 * ((value) * value * (((s) + 1) * value + s) + 2) + start;
	}
	
	private static float punch(float amplitude, float value){
		float s = 9;
		if (value == 0){
			return 0;
		}
		if (value == 1){
			return 0;
		}
		float period = 1 * 0.3f;
		s = period / (2 * Mathf.PI) * Mathf.Asin(0);
		return (amplitude * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * 1 - s) * (2 * Mathf.PI) / period));
	}
	
	/* GFX47 MOD START */
	private static float easeInElastic(float start, float end, float value){
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d) == 1) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		return -(a * Mathf.Pow(2, 10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start;
	}		
	/* GFX47 MOD END */
	
	/* GFX47 MOD START */
	//private float elastic(float start, float end, float value){
	private static float easeOutElastic(float start, float end, float value){
		/* GFX47 MOD END */
		//Thank you to rafael.marteleto for fixing this as a port over from Pedro's UnityTween
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d) == 1) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		return (a * Mathf.Pow(2, -10 * value) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) + end + start);
	}		
	
	/* GFX47 MOD START */
	private static float easeInOutElastic(float start, float end, float value){
		end -= start;
		
		float d = 1f;
		float p = d * .3f;
		float s = 0;
		float a = 0;
		
		if (value == 0) return start;
		
		if ((value /= d/2) == 2) return start + end;
		
		if (a == 0f || a < Mathf.Abs(end)){
			a = end;
			s = p / 4;
		}else{
			s = p / (2 * Mathf.PI) * Mathf.Asin(end / a);
		}
		
		if (value < 1) return -0.5f * (a * Mathf.Pow(2, 10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p)) + start;
		return a * Mathf.Pow(2, -10 * (value-=1)) * Mathf.Sin((value * d - s) * (2 * Mathf.PI) / p) * 0.5f + end + start;
	}		
	#endregion
}
public enum WarpModel{
	Once,
	Loop,
	Pingpong,
}

[System.Serializable]
public class Vector3Event:ValueEvent{
	public Vector3 Start;
	public Vector3 End;
	public Vector3 Lerp (ValueEvent.EaseType easyType,float time,WrapMode mWarp = WrapMode.Default){
		time = Mathf.Clamp (time, 0, 1);
		return new Vector3(GetValue(easyType,Start.x,End.x,time,mWarp),GetValue(easyType,Start.y,End.y,time,mWarp),GetValue(easyType,Start.z,End.z,time,mWarp));
	}
}
[System.Serializable]
public class Vector2Event:ValueEvent{
	public Vector2 Start;
	public Vector2 End;
	public Vector2 Lerp (ValueEvent.EaseType easyType,float time,WrapMode mWarp = WrapMode.Default){
		time = Mathf.Clamp (time, 0, 1);
		return new Vector2(GetValue(easyType,Start.x,End.x,time,mWarp),GetValue(easyType,Start.y,End.y,time,mWarp));
	}
}

[System.Serializable]
public class ColorEvent:ValueEvent{
	public Color Start = new Color(1,1,1,1);
	public Color End = new Color(1,1,1,1);
	public Color Lerp (ValueEvent.EaseType easyType,float time){
		time = Mathf.Clamp (time, 0, 1);
		Color color = new Color(GetValue(easyType,Start.r,End.r,time),GetValue(easyType,Start.g,End.g,time),GetValue(easyType,Start.b,End.b,time));
		return color;
	}
	public Color UnLerp (ValueEvent.EaseType easyType,float time){
		time = Mathf.Clamp (time, 0, 1);
		Color color = new Color(GetValue(easyType,End.r,Start.r,time),GetValue(easyType,End.g,Start.g,time),GetValue(easyType,End.b,Start.b,time));
		return color;
	}
	public Color LerpAplah (ValueEvent.EaseType easyType,float time){
		time = Mathf.Clamp (time, 0, 1);
		Color color = new Color(GetValue(easyType,Start.r,End.r,time),GetValue(easyType,Start.g,End.g,time),GetValue(easyType,Start.b,End.b,time),GetValue(easyType,Start.a,End.a,time));
		return color;
	}
}

[System.Serializable]
public class FloatEvent:ValueEvent{
	public bool enable;
	public float Start;
	public float End;
	public FloatEvent(float start,float end){
		Start = start;
		End = end;
	}
	public float Lerp (ValueEvent.EaseType easyType,float time,WrapMode mWarp = WrapMode.Default){
		return GetValue(easyType,Start,End,time,mWarp);
	}
}